package com.jojo.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jojo.constant.ManagerConstants;
import com.jojo.domain.SysMenu;
import com.jojo.domain.SysRole;
import com.jojo.exception.BusinessException;
import com.jojo.mapper.SysMenuMapper;
import com.jojo.service.SysMenuService;
import com.jojo.util.AuthUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.security.auth.callback.LanguageCallback;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@CacheConfig(cacheNames = "com.jojo.service.impl.SysMenuServiceImpl")
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService{

    @Resource
    @Qualifier("sysMenuMapper")
    private SysMenuMapper sysMenuMapper;

    @Override
    @Cacheable(key = "#loginUserId")
    public Set<SysMenu> queryUserMenuListByUserId(Long loginUserId) {
        //根据用户标识查询权限集合
        Set<SysMenu> sysMenus = sysMenuMapper.selectUserMenuListByUserId(loginUserId);
        //将菜单权限集合的数据转换为树结构（即：数据结构应该为层级关系）
        return transformTree(sysMenus,0L);//根目录的pid为0
    }


    /**
     *  集合转换为树结构
     *  1. 已知菜单深度 <= 2
     *  2. 未知菜单深度
     * @param sysMenus 条件筛选出来所有菜单
     * @param pid 该菜单的父节点
     * @return 根节点的菜单们
     */
    private Set<SysMenu> transformTree(Set<SysMenu> sysMenus, long pid) {
        //以下为已知菜单深度<=2的转换为树结构操作
       /* //从菜单集合中获取获取根节点集合
        Set<SysMenu> roots = sysMenus.stream()
                .filter(m -> m.getParentId().equals(pid))
                .collect(Collectors.toSet());
        //循环遍历根节点集合
        roots.forEach(root -> {
            //从菜单集合中过滤出它的父节点值与当前根节点的id值一致的菜单集合
            Set<SysMenu> child = sysMenus.stream()
                    .filter(m -> m.getParentId().equals(root.getMenuId()))
                    .collect(Collectors.toSet());
            root.setList(child);
        });*/
        //未知菜单深度
        //从菜单集合中获取获取根节点集合
        Set<SysMenu> roots = sysMenus.stream()
                .filter(m -> m.getParentId().equals(pid))
                .collect(Collectors.toSet());
        //循环遍历根节点集合
        roots.forEach(r -> r.setList(transformTree(sysMenus,r.getMenuId())));
        return roots;
    }


    /**
     * 查询所有权限
     * @return
     */
    @Override
    @Cacheable(key = ManagerConstants.SYS_ALL_MENU_KEY)
    public List<SysMenu> queryAllSysMenuList() {
        return sysMenuMapper.selectList(null);
    }

    @Override
    @CacheEvict(key = ManagerConstants.SYS_ALL_MENU_KEY)
    public Boolean saveSysMenu(SysMenu sysMenu) {
        return sysMenuMapper.insert(sysMenu) > 0;
    }

    @Override
    @CacheEvict(key = ManagerConstants.SYS_ALL_MENU_KEY)
    public Boolean modifySysMenu(SysMenu sysMenu) {
        //获取菜单类型
        if (sysMenu.getType() == 0) {
            sysMenu.setParentId(0L);
        }
        return sysMenuMapper.updateById(sysMenu) > 0;
    }

    /**
     * 如果说明当前菜单节点包含子节点，不可删除
     * @param menuId
     * @return
     */
    @Override
    @CacheEvict(key = ManagerConstants.SYS_ALL_MENU_KEY)
    public Boolean removeSysMenuById(Long menuId) {
        //根据菜单标识查询子菜单集合
        List<SysMenu> list = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getParentId, menuId)
        );
        //判断子菜单集合是否与值
        if (CollectionUtil.isNotEmpty(list) && list.size() != 0) {
            //说明当前菜单结点存在子节点,不能删除
            throw new BusinessException("当前菜单节点包含子节点集合，不可删除");
        }
        //说明当前菜单结点不存在子节点，可以进行删除

        return sysMenuMapper.deleteById(menuId) > 0;
    }


}